package com.wenyl.juc.thread;

import java.util.Date;
import java.util.concurrent.*;

/**
 * @author Swimming Dragon
 * @description: TODO
 * @date 2024年11月04日 15:40
 */
public class ThreadExecutors {
    /**
     * 创建指定线程数量的线程池，提交的任务超过线程数的部分，会进入阻塞队列
     */
    public void newFixedThreadPool(){
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        for(int i=0;i<5;i++){
            executorService.submit(() -> {
                for(int j=0;j<10;j++){
                    System.out.println(Thread.currentThread().getName()+" "+ j);
                }
            });
        }
        executorService.shutdown();
    }

    /**
     * 线程按提交顺序执行
     */
    public void newSingleThreadExecutor(){
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for(int i=0;i<5;i++){
            executorService.submit(() -> {
                for(int j=0;j<10;j++){
                    System.out.println(Thread.currentThread().getName()+" "+ j);
                }
            });
        }
        executorService.shutdown();
    }

    /**
     * 创建缓存线程池，这个线程池中线程数量不固定，会根据任务数量创建，任务执行完线程不会立即删除，而是等待一段时间，没有任务进来则清楚创建好的线程
     */
    public void newCachedThreadExecutor(){
        ExecutorService executorService = Executors.newCachedThreadPool();
        for(int i=0;i<5;i++){
            executorService.submit(() -> {
                for(int j=0;j<10;j++){
                    System.out.println(Thread.currentThread().getName()+" "+ j);
                }
            });
        }
        executorService.shutdown();
    }

    /**
     * 定时任务线程池
     */
    public void newScheduledThreadPool(){
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+",执行"+new Date());
            }
        },3,2, TimeUnit.SECONDS);
    }

    /**
     * 创建一个工作窃取线程池，前面的线程池里面的多个线程公用一个任务队列，而这个线程池则是每个线程有自己的任务队列
     * 线程发现自己队列里没有任务，则去取其他任务的线程池中的任务来执行
     */
    public void newWork(){
        CountDownLatch countDownLatch = new CountDownLatch(10);
        ExecutorService executorService = Executors.newWorkStealingPool();
        for(int i=0;i<10;i++){
            executorService.submit(() -> {
                System.out.println(Thread.currentThread().getName());
                countDownLatch.countDown();
            });
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        executorService.shutdown();
    }
}
